/************************************************************************************************
 *   深圳市摩西尔电子有限公司 @版本所有@
 *
 *   此文件用于接收卡参数构造
 *
 * 修改:
 *   1. 类型 : 创建
 *      作者 : caobingxing
 *      时间 : 2019.10.23
 *      内容 : 所有代码
 *************************************************************************************************/
/* exported  mc_sdk_recvcard */

function mc_sdk_recvcard() {
    // var THIS_MODULT_NAME = "RECVCARD";

    var XML_RECVCARD_ENTRY = "RECVCARD";
    var XML_RECVCARD_ATTR_CHIP_ID = "CHIP_ID";

    var XML_RECVCARD_HUB = "HUB";
    var XML_RECVCARD_HUB_ID = "ID";
    var XML_RECVCARD_HUB_DSP = "DSP";
    var XML_RECVCARD_HUB_SEL = "SEL";

    var XML_RECVCARD_SCAN_ORDER = "SCAN_ORDER";

    var XML_RECVCARD_TRANSLATION = "TRANSLATION";
    var XML_RECVCARD_TRANSLATION_ATTR_ROTATION = "ROTATION";
    var XML_RECVCARD_TRANSLATION_ROTATION_VAL_CNT = 5;
    var XML_RECVCARD_TRANSLATION_ATTR_SCALE = "SCALE";
    var XML_RECVCARD_TRANSLATION_SCALE_VAL_CNT = 4;
    var XML_RECVCARD_TRANSLATION_ATTR_OFFSET = "OFFSET";
    var XML_RECVCARD_TRANSLATION_OFFSET_VAL_CNT = 2;

    var XML_RECVCARD_LEDMOD_LIST = "MODLIST";
    var XML_RECVCARD_LEDMOD = "LEDMOD";
    var XML_RECVCARD_LEDMOD_ATTR_MODID = "MODULE_ID";
    var XML_RECVCARD_LEDMOD_ATTR_OFFSETX = "OFFSET_X";
    var XML_RECVCARD_LEDMOD_ATTR_OFFSETY = "OFFSET_Y";
    var XML_RECVCARD_LEDMOD_ATTR_MIRROR = "MIRROR";
    var XML_RECVCARD_LEDMOD_ATTR_ROTATION = "ROTATION";
    var XML_RECVCARD_LEDMOD_ATTR_SCALE = "SCALE";
    var MC_ZERO_EPSILON = 0.00001;
    var MAX_MODLIST_CNT = 255;
    var MAX_MODLIST_MOD_CNT = 4096;

    var PI = 3.1415926;

    var m_str_ctrl_chip = "";
    var m_str_scan_order = "";
    var m_st_translation = new mc_recvcard_translation();
    var m_vst_modlist_ary = [];
    var m_obj_revcard_msg = new mc_revcard_msg();
    var m_str_hub_id = "";
    var m_str_hub_dsp = "";
    var m_str_hub_sel = "";
    var m_obj_hub_msg = {};


    function mc_revcard_msg() {
        this.ui_img_w = 0;
        this.ui_img_y = 0;
        this.reset = function () {
            this.ui_img_w = 0;
            this.ui_img_y = 0;
        };
    }

    function mc_recvcard_mod() {
        this.u32_x_offset = 0;
        this.u32_y_offset = 0;
        this.str_mod_id = "";
        this.str_mirror = "";
        this.str_rotation = "";
        this.str_scale = "";
        this.ui_jx_num = -1;
    }

    function mc_recvcard_modlist() {
        this.vst_mod_ary = [];
        this.mp_pinpair_ary = {};

        // var str_pinpair_expr = "";
        this.add_pin_pair_node = function (ac_pin_name, u32_dsp_idx) {
            if (!ac_pin_name) {
                return false;
            }

            ac_pin_name = ac_pin_name.toUpperCase();

            for (var key in this.mp_pinpair_ary) {
                if (key === u32_dsp_idx) {
                    this.mp_pinpair_ary[key] = ac_pin_name;
                    return true;
                }
            }

            this.mp_pinpair_ary[u32_dsp_idx] = ac_pin_name;
            return true;
        };

        this.delete_pin_pair_by_dsp = function (u32_dsp_idx) {
            delete this.mp_pinpair_ary[u32_dsp_idx];
            return true;
        };
        this.delete_pin_pair_by_pin = function (ac_pin_name) {
            if (!ac_pin_name) {
                return false;
            }

            var str_pin_name = ac_pin_name.toUpperCase();

            var b_erase = true;

            while (b_erase) {
                b_erase = false;
                var keys = Object.keys(this.mp_pinpair_ary);

                for (var i = 0; i < keys.length; i++) {
                    var str_pin_name_exist = this.mp_pinpair_ary[keys[i]].toUpperCase();

                    if (str_pin_name_exist === str_pin_name) {
                        b_erase = true;
                        delete this.mp_pinpair_ary[keys[i]];
                        break;
                    }
                }
            }
            return true;
        };

        this.set_pin_pair_exp = function (ac_pinpari_exp) {
            this.mp_pinpair_ary = {};
            if (!ac_pinpari_exp) {
                return false;
            }

            var str_pinpair_desp = ac_pinpari_exp;

            /* erase all blank space, note if in version befour C++11, used isspace replace lambda */
            str_pinpair_desp = str_pinpair_desp.replace(/\s+/g, "");

            /* replace sepc code */
            str_pinpair_desp = str_pinpair_desp.replace(/（/g, "(");
            str_pinpair_desp = str_pinpair_desp.replace(/）/g, ")");
            str_pinpair_desp = str_pinpair_desp.replace(/；/g, ",");
            str_pinpair_desp = str_pinpair_desp.replace(/，/g, ",");
            str_pinpair_desp = str_pinpair_desp.replace(/;/g, ",");
            str_pinpair_desp = str_pinpair_desp.replace(/：/g, ":");

            /* upper case */
            str_pinpair_desp = str_pinpair_desp.toUpperCase();
            str_pinpair_desp = "," + str_pinpair_desp + ",";

            /* analyize */
            var ui_find_pos = 0;
            var ui_last_pos = 0;

            while (true) {
                /* get expression section */
                ui_find_pos = str_pinpair_desp.indexOf(",", ui_last_pos + 1);
                if (-1 === ui_find_pos) {
                    break;
                }

                var str_sub_expression = str_pinpair_desp.slice(ui_last_pos, ui_find_pos + 1);

                ui_last_pos = ui_find_pos;
                /* at least has tow ',' */
                if (4 > str_sub_expression.length) {
                    continue;
                }

                var ac_dsp_key_val = "DSP";
                var ui_dsp_key_len = ac_dsp_key_val.length;

                if (-1 === str_sub_expression.indexOf(":") || -1 === str_sub_expression.indexOf(ac_dsp_key_val)) {
                    continue;
                }

                var u32_dsp_id = 0;
                var str_dsp_txt = str_sub_expression.slice(str_sub_expression.indexOf(ac_dsp_key_val) + ui_dsp_key_len);

                if (-1 === "0123456789".indexOf(str_dsp_txt.slice(0, 1))) {
                    continue;
                }

                u32_dsp_id = parseInt(str_dsp_txt, 10);
                var str_pin_name = str_sub_expression.slice(str_sub_expression.indexOf(":") + 1);

                if (-1 !== str_pin_name.indexOf(")")) {
                    str_pin_name = str_pin_name.slice(0, str_pin_name.indexOf(")"));
                }

                this.mp_pinpair_ary[u32_dsp_id] = str_pin_name;
            }
            return true;
        };

        this.get_pin_pair_exp = function () {
            var str_pinpair_exp = "";
            var keys = Object.keys(this.mp_pinpair_ary);

            for (var i = 0; i < keys.length; i++) {
                str_pinpair_exp += "(DSP" + keys[i] + ":" + this.mp_pinpair_ary[keys[i]] + "),";
            }
            var str_pinpair_expr = str_pinpair_exp;

            if (0 < str_pinpair_expr.length && "," === str_pinpair_expr.slice(-1)) {
                str_pinpair_expr = str_pinpair_expr.slice(0, -1);
            }

            return str_pinpair_expr;
        };
    }

    function mc_recvcard_translation() {
        this.vdf_rotation = [];
        this.vdf_scale = [];
        this.vdf_offset = [];

        this.reset = function () {
            this.vdf_rotation = [];
            this.vdf_scale = [];
            this.vdf_offset = [];
        };
    }

    var m_str_descript_xml_dst = "";

    function reset() {
        m_str_ctrl_chip = "";
        m_str_hub_id = "";
        m_str_hub_dsp = "";
        m_str_hub_sel = "";
        m_str_scan_order = "";
        m_st_translation.reset();
        m_vst_modlist_ary = [];
        m_obj_revcard_msg.reset();
        m_obj_hub_msg = {};
        return true;
    }


    function parse_module_list(pcla_elem_root) {
        var pxml_elm_ledmod_list = pcla_elem_root.getElementsByTagName(XML_RECVCARD_LEDMOD_LIST);
        var ac_value = "";

        for (var idx_mod_list = 0; idx_mod_list < pxml_elm_ledmod_list.length; idx_mod_list++) {
            var st_modlist = new mc_recvcard_modlist();

            m_vst_modlist_ary.push(st_modlist);

            /* get led-module array */
            var pxml_elm_ledmod = pxml_elm_ledmod_list[idx_mod_list].getElementsByTagName(XML_RECVCARD_LEDMOD);

            for (var idx_ledmod = 0; idx_ledmod < pxml_elm_ledmod.length; idx_ledmod++) {
                var st_mod = new mc_recvcard_mod();

                st_modlist.vst_mod_ary.push(st_mod);

                /* get attribute */
                ac_value = pxml_elm_ledmod[idx_ledmod].getAttribute(XML_RECVCARD_LEDMOD_ATTR_MODID);

                if (ac_value) {
                    st_mod.str_mod_id = ac_value;
                }

                ac_value = pxml_elm_ledmod[idx_ledmod].getAttribute(XML_RECVCARD_LEDMOD_ATTR_OFFSETX);
                if (ac_value) {
                    st_mod.u32_x_offset = parseInt(ac_value, 10);
                }

                ac_value = pxml_elm_ledmod[idx_ledmod].getAttribute(XML_RECVCARD_LEDMOD_ATTR_OFFSETY);
                if (ac_value) {
                    st_mod.u32_y_offset = parseInt(ac_value, 10);
                }

                /* get dsp-connect descript */
                if (!Object.keys(st_modlist.mp_pinpair_ary).length) {
                    ac_value = pxml_elm_ledmod[idx_ledmod].textContent;
                    if (ac_value) {
                        st_modlist.set_pin_pair_exp(ac_value);
                    }
                }
            }
        }
    }

    function parse_translation(pcla_elem_root) {
        var pxml_elm_translation = pcla_elem_root.getElementsByTagName(XML_RECVCARD_TRANSLATION);
        var ac_value = "";
        var str_value = "";
        var ui_find_pos = 0;
        var vdf_value;
        var idx = 0;
        var m;

        if (pxml_elm_translation.length) {
            pxml_elm_translation = pxml_elm_translation[0];
            ac_value = pxml_elm_translation.getAttribute(XML_RECVCARD_TRANSLATION_ATTR_ROTATION);
            if (ac_value) {
                str_value = ac_value;
                ui_find_pos = 0;
                vdf_value = m_st_translation.vdf_rotation;

                for (idx = 0; idx < XML_RECVCARD_TRANSLATION_ROTATION_VAL_CNT; idx++) {
                    m = str_value.slice(ui_find_pos).match(/[\d.]/);

                    if (!m) {
                        break;
                    }
                    ui_find_pos += m.index;
                    vdf_value.push(parseFloat(str_value.slice(ui_find_pos)));

                    m = str_value.slice(ui_find_pos).match(/[^\d.]/);
                    if (m) {
                        ui_find_pos += m.index;
                    }
                }

                if (vdf_value.length !== XML_RECVCARD_TRANSLATION_ROTATION_VAL_CNT) {
                    vdf_value = [];
                }
            }

            ac_value = pxml_elm_translation.getAttribute(XML_RECVCARD_TRANSLATION_ATTR_SCALE);
            if (ac_value) {
                str_value = ac_value;
                ui_find_pos = 0;
                vdf_value = m_st_translation.vdf_scale;
                for (idx = 0; idx < XML_RECVCARD_TRANSLATION_SCALE_VAL_CNT; idx++) {
                    m = str_value.slice(ui_find_pos).match(/[\d.]/);
                    if (!m) {
                        break;
                    }
                    ui_find_pos += m.index;
                    vdf_value.push(parseFloat(str_value.slice(ui_find_pos)));

                    m = str_value.slice(ui_find_pos).match(/[^\d.]/);
                    if (m) {
                        ui_find_pos += m.index;
                    }
                }

                if (vdf_value.length !== XML_RECVCARD_TRANSLATION_SCALE_VAL_CNT) {
                    vdf_value = [];
                }
            }

            ac_value = pxml_elm_translation.getAttribute(XML_RECVCARD_TRANSLATION_ATTR_OFFSET);
            if (ac_value) {
                str_value = ac_value;

                ui_find_pos = 0;
                vdf_value = m_st_translation.vdf_offset;
                for (idx = 0; idx < XML_RECVCARD_TRANSLATION_OFFSET_VAL_CNT; idx++) {
                    m = str_value.slice(ui_find_pos).match(/[\d.]/);
                    if (!m) {
                        break;
                    }
                    ui_find_pos += m.index;
                    vdf_value.push(parseFloat(str_value.slice(ui_find_pos)));

                    m = str_value.slice(ui_find_pos).match(/[^\d.]/);
                    if (m) {
                        ui_find_pos += m.index;
                    }
                }

                if (vdf_value.length !== XML_RECVCARD_TRANSLATION_OFFSET_VAL_CNT) {
                    vdf_value = [];
                }
            }
        }
    }

    function set_xml_data(ac_xml_data) {
        reset();
        if (!ac_xml_data) {
            return false;
        }
        var cla_xml_doc = new DOMParser();
        var cla_doc = cla_xml_doc.parseFromString(ac_xml_data, "text/xml");
        /* get head entry */
        var pcla_elem_root = cla_doc.getElementsByTagName(XML_RECVCARD_ENTRY);

        if (!pcla_elem_root.length) {
            return false;
        }

        var ac_value = "";

        pcla_elem_root = pcla_elem_root[0];
        /* get control chip name */
        ac_value = pcla_elem_root.getAttribute(XML_RECVCARD_ATTR_CHIP_ID);
        if (ac_value) {
            m_str_ctrl_chip = ac_value;
        }
        /* get hub information */
        var pxml_elm_hub = pcla_elem_root.getElementsByTagName(XML_RECVCARD_HUB);

        if (!pxml_elm_hub.length) {
            return false;
        }

        pxml_elm_hub = pxml_elm_hub[0];
        ac_value = pxml_elm_hub.getAttribute(XML_RECVCARD_HUB_ID);
        if (ac_value) {
            m_str_hub_id = ac_value;
        }

        var pxml_elm_hub_dsp = pxml_elm_hub.getElementsByTagName(XML_RECVCARD_HUB_DSP);

        if (pxml_elm_hub_dsp.length) {
            ac_value = pxml_elm_hub_dsp[0].textContent;
            if (ac_value) {
                m_str_hub_dsp = ac_value;
            }
        }

        var pxml_elm_hub_sel = pxml_elm_hub.getElementsByTagName(XML_RECVCARD_HUB_SEL);

        if (pxml_elm_hub_sel.length) {
            ac_value = pxml_elm_hub_sel[0].textContent;
            if (ac_value) {
                m_str_hub_sel = ac_value;
            }
        }

        var pxml_elm_scan_order = pcla_elem_root.getElementsByTagName(XML_RECVCARD_SCAN_ORDER);

        if (pxml_elm_scan_order.length) {
            ac_value = pxml_elm_scan_order[0].textContent;
            if (ac_value) {
                m_str_scan_order = ac_value;
            }
        }

        parse_translation(pcla_elem_root);
        /* module list */
        parse_module_list(pcla_elem_root);
        return true;
    }

    function get_xml_data() {
        var str_xml_data = "";

        str_xml_data += "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
        str_xml_data += "<" + XML_RECVCARD_ENTRY + " " + XML_RECVCARD_ATTR_CHIP_ID + "=\"" + m_str_ctrl_chip + "\" VERSION=\"1.0\">\n";

        /* hub information */
        str_xml_data += "  <" + XML_RECVCARD_HUB + " " + XML_RECVCARD_HUB_ID + "=\"" + m_str_hub_id + "\">\n";
        str_xml_data += "    <" + XML_RECVCARD_HUB_DSP + ">" + m_str_hub_dsp + "</" + XML_RECVCARD_HUB_DSP + ">\n";
        str_xml_data += "    <" + XML_RECVCARD_HUB_SEL + ">" + m_str_hub_sel + "</" + XML_RECVCARD_HUB_SEL + ">\n";
        str_xml_data += "  </" + XML_RECVCARD_HUB + ">\n";

        /* scan refresh order */
        str_xml_data += "  <" + XML_RECVCARD_SCAN_ORDER + ">" + m_str_scan_order + "</" + XML_RECVCARD_SCAN_ORDER + ">\n";
        var ac_value = "";

        if (m_st_translation.vdf_rotation.length === XML_RECVCARD_TRANSLATION_ROTATION_VAL_CNT ||
            m_st_translation.vdf_scale.length === XML_RECVCARD_TRANSLATION_SCALE_VAL_CNT ||
            m_st_translation.vdf_offset.length === XML_RECVCARD_TRANSLATION_OFFSET_VAL_CNT) {
            str_xml_data += "  <" + XML_RECVCARD_TRANSLATION + " ";
            if (m_st_translation.vdf_rotation.length === XML_RECVCARD_TRANSLATION_ROTATION_VAL_CNT) {
                ac_value += XML_RECVCARD_TRANSLATION_ATTR_ROTATION + "=" + "\"" + m_st_translation.vdf_rotation[0] +
                    "," + m_st_translation.vdf_rotation[1] + "," + m_st_translation.vdf_rotation[2] + "," +
                    m_st_translation.vdf_rotation[3] + "," + m_st_translation.vdf_rotation[4] + "\" ";
                str_xml_data += ac_value;
            }

            if (m_st_translation.vdf_scale.length === XML_RECVCARD_TRANSLATION_SCALE_VAL_CNT) {
                ac_value = "";
                ac_value += XML_RECVCARD_TRANSLATION_ATTR_SCALE + "=" + "\"" + m_st_translation.vdf_scale[0] +
                    "," + m_st_translation.vdf_scale[1] + "," + m_st_translation.vdf_scale[2] + "," +
                    m_st_translation.vdf_scale[3] + "\" ";
                str_xml_data += ac_value;
            }

            if (m_st_translation.vdf_offset.length === XML_RECVCARD_TRANSLATION_OFFSET_VAL_CNT) {
                ac_value = "";
                ac_value += XML_RECVCARD_TRANSLATION_ATTR_OFFSET + "=" + "\"" + m_st_translation.vdf_offset[1] +
                    "," + m_st_translation.vdf_offset[1] + "\" ";
                str_xml_data += ac_value;
            }
            str_xml_data += "/>";
        }

        /* module list ary */
        for (var idx_modlist = 0; idx_modlist < m_vst_modlist_ary.length; idx_modlist++) {
            var st_modlist = m_vst_modlist_ary[idx_modlist];

            // if (1 > Object.keys(st_modlist.mp_pinpair_ary).length) {
            //     continue;
            // }

            str_xml_data += "  <" + XML_RECVCARD_LEDMOD_LIST + ">\n";
            for (var idx_ledmod = 0; idx_ledmod < st_modlist.vst_mod_ary.length; idx_ledmod++) {
                var st_mod = st_modlist.vst_mod_ary[idx_ledmod];

                if (1 > st_mod.str_mod_id.length) {
                    continue;
                }

                str_xml_data += "    <" + XML_RECVCARD_LEDMOD + " " +
                    XML_RECVCARD_LEDMOD_ATTR_MODID + "=\"" + st_mod.str_mod_id + "\" " +
                    XML_RECVCARD_LEDMOD_ATTR_OFFSETX + "=\"" + st_mod.u32_x_offset + "\"  " +
                    XML_RECVCARD_LEDMOD_ATTR_OFFSETY + "=\"" + st_mod.u32_y_offset + "\" " +
                    XML_RECVCARD_LEDMOD_ATTR_MIRROR + "=\"" + st_mod.str_mirror + "\" " +
                    XML_RECVCARD_LEDMOD_ATTR_ROTATION + "=\"" + st_mod.str_rotation + "\" " +
                    XML_RECVCARD_LEDMOD_ATTR_SCALE + "=\"" + st_mod.str_scale + "\">" +
                    st_modlist.get_pin_pair_exp() +
                    "</" + XML_RECVCARD_LEDMOD + ">\n";
            }

            str_xml_data += "  </" + XML_RECVCARD_LEDMOD_LIST + ">\n";
        }

        str_xml_data += "</" + XML_RECVCARD_ENTRY + ">\n";

        m_str_descript_xml_dst = str_xml_data;
        return m_str_descript_xml_dst;
    }

    function set_ctrl_chip(ac_ctrl_chip) {
        if (ac_ctrl_chip) {
            m_str_ctrl_chip = ac_ctrl_chip;
            return true;
        }
        m_str_ctrl_chip = "";
        return false;
    }

    function get_ctrl_chip() {
        return m_str_ctrl_chip;
    }

    function set_hub_id(ac_hub_id) {
        if (ac_hub_id) {
            m_str_hub_id = ac_hub_id;
            return true;
        }
        m_str_hub_id = "";
        return false;
    }

    function get_hub_id() {
        return m_str_hub_id;
    }

    function set_hub_dsp(ac_hub_dsp) {
        if (ac_hub_dsp) {
            m_str_hub_dsp = ac_hub_dsp;
            return true;
        }
        m_str_hub_dsp = "";
        return false;
    }

    function get_hub_dsp() {
        return m_str_hub_dsp;
    }

    function set_hub_sel(ac_hub_sel) {
        if (ac_hub_sel) {
            m_str_hub_sel = ac_hub_sel;
            return true;
        }
        m_str_hub_sel = "";
        return false;
    }

    function get_hub_sel() {
        return m_str_hub_sel;
    }

    function set_scan_order(ac_scan_order) {
        if (ac_scan_order) {
            m_str_scan_order = ac_scan_order;
            return true;
        }
        m_str_scan_order = "";
        return false;
    }

    function get_scan_order() {
        return m_str_scan_order;
    }

    function set_rotation(adf_base_pnt, adf_vector, df_angle) {
        if (!Array.isArray(adf_base_pnt) || !Array.isArray(adf_vector) || isNaN(parseFloat(df_angle))) {
            return false;
        }
        m_st_translation.vdf_rotation = [];
        if (!adf_base_pnt && !adf_vector) {
            return false;
        }
        m_st_translation.vdf_rotation.length = XML_RECVCARD_TRANSLATION_ROTATION_VAL_CNT;
        for (var i = 0; i < m_st_translation.vdf_rotation.length; i++) {
            m_st_translation.vdf_rotation[i] = 0;
        }
        if (adf_base_pnt) {
            m_st_translation.vdf_rotation[0] = adf_base_pnt[0];
            m_st_translation.vdf_rotation[1] = adf_base_pnt[1];
        }
        if (adf_vector) {
            m_st_translation.vdf_rotation[2] = adf_vector[0];
            m_st_translation.vdf_rotation[3] = adf_vector[1];
        }
        m_st_translation.vdf_rotation[4] = df_angle;
        return true;
    }

    function set_scale(adf_base_pnt, adf_scale) {
        if (!Array.isArray(adf_base_pnt) || !Array.isArray(adf_scale)) {
            return false;
        }
        m_st_translation.vdf_scale = [];
        if (!adf_base_pnt || !adf_scale) {
            return false;
        }

        m_st_translation.vdf_scale.length = XML_RECVCARD_TRANSLATION_SCALE_VAL_CNT;
        m_st_translation.vdf_scale[0] = adf_base_pnt[0];
        m_st_translation.vdf_scale[1] = adf_base_pnt[1];
        m_st_translation.vdf_scale[2] = adf_scale[0];
        m_st_translation.vdf_scale[3] = adf_scale[1];
        return true;
    }

    function set_offset(adf_offset) {
        if (!Array.isArray(adf_offset)) {
            return false;
        }
        m_st_translation.vdf_offset = [];
        if (!adf_offset) {
            return false;
        }

        m_st_translation.vdf_offset.length = XML_RECVCARD_TRANSLATION_OFFSET_VAL_CNT;
        m_st_translation.vdf_offset[0] = adf_offset[0];
        m_st_translation.vdf_offset[1] = adf_offset[1];
        return true;
    }

    function get_rotation() {
        var obj_ret = {
            adf_base_pnt: [],
            adf_vector: [],
            df_angle: 0
        };

        if (XML_RECVCARD_TRANSLATION_ROTATION_VAL_CNT === m_st_translation.vdf_rotation.length) {
            obj_ret.adf_base_pnt[0] = Math.abs(m_st_translation.vdf_rotation[0]) < MC_ZERO_EPSILON ? 0.0 : m_st_translation.vdf_rotation[0];
            obj_ret.adf_base_pnt[1] = Math.abs(m_st_translation.vdf_rotation[1]) < MC_ZERO_EPSILON ? 0.0 : m_st_translation.vdf_rotation[1];
        } else {
            obj_ret.adf_base_pnt[0] = 0.0;
            obj_ret.adf_base_pnt[1] = 0.0;
        }

        if (XML_RECVCARD_TRANSLATION_ROTATION_VAL_CNT === m_st_translation.vdf_rotation.length) {
            obj_ret.adf_vector[0] = Math.abs(m_st_translation.vdf_rotation[2]) < MC_ZERO_EPSILON ? 0.0 : m_st_translation.vdf_rotation[2];
            obj_ret.adf_vector[1] = Math.abs(m_st_translation.vdf_rotation[3]) < MC_ZERO_EPSILON ? 0.0 : m_st_translation.vdf_rotation[3];
        } else {
            obj_ret.adf_vector[0] = 0.0;
            obj_ret.adf_vector[1] = 0.0;
        }

        if (XML_RECVCARD_TRANSLATION_ROTATION_VAL_CNT === m_st_translation.vdf_rotation.length) {
            obj_ret.df_angle = Math.abs(m_st_translation.vdf_rotation[4]) < MC_ZERO_EPSILON ? 0.0 : m_st_translation.vdf_rotation[4];
        } else {
            obj_ret.df_angle = 0;
        }
        return obj_ret;
    }

    function get_scale() {
        var obj_ret = {
            adf_base_pnt: [],
            adf_scale: []
        };

        if (XML_RECVCARD_TRANSLATION_SCALE_VAL_CNT === m_st_translation.vdf_scale.length) {
            obj_ret.adf_base_pnt[0] = Math.abs(m_st_translation.vdf_scale[0]) < MC_ZERO_EPSILON ? 0.0 : m_st_translation.vdf_scale[0];
            obj_ret.adf_base_pnt[1] = Math.abs(m_st_translation.vdf_scale[1]) < MC_ZERO_EPSILON ? 0.0 : m_st_translation.vdf_scale[1];
        } else {
            obj_ret.adf_base_pnt[0] = 0.0;
            obj_ret.adf_base_pnt[1] = 0.0;
        }

        if (XML_RECVCARD_TRANSLATION_SCALE_VAL_CNT === m_st_translation.vdf_scale.length) {
            obj_ret.adf_scale[0] = Math.abs(m_st_translation.vdf_scale[2]) < MC_ZERO_EPSILON ? 0.0 : m_st_translation.vdf_scale[2];
            obj_ret.adf_scale[1] = Math.abs(m_st_translation.vdf_scale[3]) < MC_ZERO_EPSILON ? 0.0 : m_st_translation.vdf_scale[3];
        } else {
            obj_ret.adf_scale[0] = 1.0;
            obj_ret.adf_scale[1] = 1.0;
        }
        return obj_ret;
    }

    function get_offset() {
        var adf_offset = [];

        if (XML_RECVCARD_TRANSLATION_OFFSET_VAL_CNT === m_st_translation.vdf_offset.length) {
            adf_offset[0] = Math.abs(m_st_translation.vdf_offset[0]) < MC_ZERO_EPSILON ? 0.0 : m_st_translation.vdf_offset[0];
            adf_offset[1] = Math.abs(m_st_translation.vdf_offset[1]) < MC_ZERO_EPSILON ? 0.0 : m_st_translation.vdf_offset[1];
        } else {
            adf_offset[0] = 0.0;
            adf_offset[1] = 0.0;
        }
        return adf_offset;
    }

    function get_modlist_cnt() {
        return m_vst_modlist_ary.length;
    }

    function get_modlist_pin_pair_exp(u32_modlist_idx) {
        if (isNaN(parseInt(u32_modlist_idx, 10))) {
            return "";
        }
        if (get_modlist_cnt() <= u32_modlist_idx) {
            return "";
        }

        return m_vst_modlist_ary[u32_modlist_idx].get_pin_pair_exp();
    }

    function get_modlist_dsp_pin(u32_modlist_idx, u32_dsp_idx) {
        if (isNaN(parseInt(u32_modlist_idx, 10))) {
            return "";
        }
        if (get_modlist_cnt() <= u32_modlist_idx) {
            return "";
        }

        if (Object.prototype.hasOwnProperty.call(m_vst_modlist_ary[u32_modlist_idx].mp_pinpair_ary, u32_dsp_idx)) {
            return m_vst_modlist_ary[u32_modlist_idx].mp_pinpair_ary[u32_dsp_idx];
        }
        return "";
    }

    function get_modlist_pin_dsp(u32_modlist_idx, ac_pin_name) {
        if (isNaN(parseInt(u32_modlist_idx, 10))) {
            return Number.MAX_VALUE;
        }
        if (get_modlist_cnt() <= u32_modlist_idx || !ac_pin_name) {
            return Number.MAX_VALUE;
        }

        var str_pin_name = ac_pin_name.toUpperCase();

        var keys = Object.keys(m_vst_modlist_ary[u32_modlist_idx].mp_pinpair_ary);

        for (var i = 0; i < keys.length; i++) {
            var str_pin_name_tmp = m_vst_modlist_ary[u32_modlist_idx].mp_pinpair_ary[keys[i]];

            str_pin_name_tmp = str_pin_name_tmp.toUpperCase();
            if (str_pin_name_tmp === str_pin_name) {
                return keys[i];
            }
        }

        return Number.MAX_VALUE;
    }

    function delete_modlist_pin_pair_by_dsp(u32_modlist_idx, u32_dsp_idx) {
        if (isNaN(parseInt(u32_modlist_idx, 10))) {
            return false;
        }
        if (get_modlist_cnt() <= u32_modlist_idx) {
            return false;
        }
        m_vst_modlist_ary[u32_modlist_idx].delete_pin_pair_by_dsp(u32_dsp_idx);
        return true;
    }

    function delete_modlist_pin_pair_by_pin(u32_modlist_idx, ac_pin_name) {
        if (isNaN(parseInt(u32_modlist_idx, 10))) {
            return false;
        }
        if (get_modlist_cnt() <= u32_modlist_idx) {
            return false;
        }
        m_vst_modlist_ary[u32_modlist_idx].delete_pin_pair_by_pin(ac_pin_name);
        return true;
    }

    function set_modlist_pin_pair_exp(u32_modlist_idx, ac_exp) {
        if (isNaN(parseInt(u32_modlist_idx, 10))) {
            return false;
        }
        if (MAX_MODLIST_CNT < u32_modlist_idx || !ac_exp) {
            return false;
        }

        if (get_modlist_cnt() <= u32_modlist_idx) {
            for (var i = 0; i < u32_modlist_idx + 1 - m_vst_modlist_ary.length; i++) {
                m_vst_modlist_ary.push(new mc_recvcard_modlist());
            }
        }

        m_vst_modlist_ary[u32_modlist_idx].set_pin_pair_exp(ac_exp);

        return true;
    }

    function get_mod_cnt(u32_modlist_idx) {
        if (isNaN(parseInt(u32_modlist_idx, 10))) {
            return 0;
        }
        if (get_modlist_cnt() <= u32_modlist_idx) {
            return 0;
        }

        return m_vst_modlist_ary[u32_modlist_idx].vst_mod_ary.length;
    }

    function get_mod_id(u32_modlist_idx, u32_mod_idx) {
        if (isNaN(parseInt(u32_modlist_idx, 10)) || isNaN(parseInt(u32_mod_idx, 10))) {
            return "";
        }
        if (get_mod_cnt(u32_modlist_idx) <= u32_mod_idx) {
            return "";
        }

        return m_vst_modlist_ary[u32_modlist_idx].vst_mod_ary[u32_mod_idx].str_mod_id;
    }

    function get_mod_x_offset(u32_modlist_idx, u32_mod_idx) {
        if (isNaN(parseInt(u32_modlist_idx, 10)) || isNaN(parseInt(u32_mod_idx, 10))) {
            return 0;
        }
        if (get_mod_cnt(u32_modlist_idx) <= u32_mod_idx) {
            return 0;
        }

        return m_vst_modlist_ary[u32_modlist_idx].vst_mod_ary[u32_mod_idx].u32_x_offset;
    }

    function get_mod_y_offset(u32_modlist_idx, u32_mod_idx) {
        if (isNaN(parseInt(u32_modlist_idx, 10)) || isNaN(parseInt(u32_mod_idx, 10))) {
            return 0;
        }
        if (get_mod_cnt(u32_modlist_idx) <= u32_mod_idx) {
            return 0;
        }

        return m_vst_modlist_ary[u32_modlist_idx].vst_mod_ary[u32_mod_idx].u32_y_offset;
    }
    function get_mod_mirror(u32_modlist_idx, u32_mod_idx) {
        if (isNaN(parseInt(u32_modlist_idx, 10)) || isNaN(parseInt(u32_mod_idx, 10))) {
            return 0;
        }
        if (get_mod_cnt(u32_modlist_idx) <= u32_mod_idx) {
            return 0;
        }

        return m_vst_modlist_ary[u32_modlist_idx].vst_mod_ary[u32_mod_idx].str_mirror;
    }
    function get_mod_rotation(u32_modlist_idx, u32_mod_idx) {
        if (isNaN(parseInt(u32_modlist_idx, 10)) || isNaN(parseInt(u32_mod_idx, 10))) {
            return 0;
        }
        if (get_mod_cnt(u32_modlist_idx) <= u32_mod_idx) {
            return 0;
        }

        return m_vst_modlist_ary[u32_modlist_idx].vst_mod_ary[u32_mod_idx].str_rotation;
    }
    function get_mod_scale(u32_modlist_idx, u32_mod_idx) {
        if (isNaN(parseInt(u32_modlist_idx, 10)) || isNaN(parseInt(u32_mod_idx, 10))) {
            return 0;
        }
        if (get_mod_cnt(u32_modlist_idx) <= u32_mod_idx) {
            return 0;
        }

        return m_vst_modlist_ary[u32_modlist_idx].vst_mod_ary[u32_mod_idx].str_scale;
    }

    function clear_modlist_mods(u32_modlist_idx) {
        if (get_modlist_cnt() <= u32_modlist_idx) {
            return false;
        }

        m_vst_modlist_ary[u32_modlist_idx].vst_mod_ary = [];
        return true;
    }

    function clear_modlist() {
        m_vst_modlist_ary = [];
        return true;
    }

    function set_mod_info(u32_modlist_idx, u32_mod_idx, ac_mod_id, u32_x_offset, u32_y_offset,str_mirror,str_rotation,str_scale,str_cut) {
        if (isNaN(parseInt(u32_modlist_idx, 10)) || isNaN(parseInt(u32_mod_idx, 10))) {
            return false;
        }
        if (MAX_MODLIST_CNT < u32_modlist_idx || MAX_MODLIST_MOD_CNT < u32_mod_idx || !ac_mod_id) {
            return false;
        }

        var i = 0;

        if (get_modlist_cnt() <= u32_modlist_idx) {
            for (i = 0; i < u32_modlist_idx + 1 - m_vst_modlist_ary.length; i++) {
                m_vst_modlist_ary.push(new mc_recvcard_modlist());
            }
        }

        if (get_mod_cnt(u32_modlist_idx) <= u32_mod_idx) {
            for (i = 0; i < u32_mod_idx + 1 - m_vst_modlist_ary[u32_modlist_idx].vst_mod_ary.length; i++) {
                m_vst_modlist_ary[u32_modlist_idx].vst_mod_ary.push(new mc_recvcard_mod());
            }
        }

        m_vst_modlist_ary[u32_modlist_idx].vst_mod_ary[u32_mod_idx].str_mod_id = ac_mod_id;
        if (!isNaN(parseInt(u32_x_offset, 10)) && !isNaN(parseInt(u32_y_offset, 10))) {
            m_vst_modlist_ary[u32_modlist_idx].vst_mod_ary[u32_mod_idx].u32_x_offset = u32_x_offset;
            m_vst_modlist_ary[u32_modlist_idx].vst_mod_ary[u32_mod_idx].u32_y_offset = u32_y_offset;
            m_vst_modlist_ary[u32_modlist_idx].vst_mod_ary[u32_mod_idx].str_mirror = "string" === typeof str_mirror ? str_mirror : "0";
            m_vst_modlist_ary[u32_modlist_idx].vst_mod_ary[u32_mod_idx].str_rotation = "string" === typeof str_rotation ? str_rotation : "0,0,0";
            m_vst_modlist_ary[u32_modlist_idx].vst_mod_ary[u32_mod_idx].str_scale = "string" === typeof str_scale ? str_scale : "0.0,0.0,1.0,1.0";
            m_vst_modlist_ary[u32_modlist_idx].vst_mod_ary[u32_mod_idx].str_cut = "string" === typeof str_cut ? str_cut : "0,0,0,0";
        }

        return true;
    }

    function reverse_modlist_mod_order(u32_modlist_idx) {
        if (isNaN(parseInt(u32_modlist_idx, 10))) {
            return false;
        }
        if (get_modlist_cnt() <= u32_modlist_idx) {
            return false;
        }

        m_vst_modlist_ary[u32_modlist_idx].vst_mod_ary.reverse();

        return true;
    }

    /********** Xsc ****************************************************************************************/

    /************************************************************************************************
    * 类型:
    *    内部函数
    * 功能:
    *    获取箱体内最小jx 下 第一个mod的名称
    * 参数:
    *    NA
    * 返回：
    *    @returns {Promise<String>} 箱体中最小jx下第一个模组名称
    * 修改:
    *   1. 类型 : 创建
    *      作者 : 徐烁超
    *      时间 : 2020.9.27
    *      内容 : 所有代码
    ************************************************************************************************/
    function get_first_mod_name() {
        if (0 >= m_vst_modlist_ary.length) {
            return "";
        }
        var str_fist_mod_name = m_vst_modlist_ary[0].vst_mod_ary[0].str_mod_id;
        var ui_min_dsp_val = Number(m_vst_modlist_ary[0].get_pin_pair_exp().match(/\d+/g)[0]);

        for (var idx_modlist = 1; idx_modlist < m_vst_modlist_ary.length; idx_modlist++) {
            var obj_ledmod_data = m_vst_modlist_ary[idx_modlist];
            var ui_dsp_value = Number(obj_ledmod_data.get_pin_pair_exp().match(/\d+/g)[0]);

            if (ui_dsp_value < ui_min_dsp_val) {
                ui_min_dsp_val = ui_dsp_value;
                str_fist_mod_name = m_vst_modlist_ary[idx_modlist].vst_mod_ary[0].str_mod_id;
            }
        }

        return str_fist_mod_name;
    }

    /************************************************************************************************
    * 类型:
    *    内部函数
    * 功能:
    *    存入hub描述信息
    * 参数:
    *    @param {Promise<Object>} obj_hub_msg hub描述对象
    * 返回：
    *    @returns {Promise<Boolean>} 储存结果
    * 修改:
    *   1. 类型 : 创建
    *      作者 : 徐烁超
    *      时间 : 2020.10.29
    *      内容 : 所有代码
    ************************************************************************************************/
    function set_hub_msg(obj_hub_msg) {
        if (
            !obj_hub_msg ||
            !obj_hub_msg.str_name
        ) {
            return false;
        }

        m_str_hub_id = obj_hub_msg.str_name;

        if (
            obj_hub_msg.ary_child_pin[0].ary_st_dat
        ) {
            m_str_hub_dsp = "";

            var ary_dat_value = obj_hub_msg.ary_child_pin[0].ary_st_dat;

            for (var idx_dat = 0; idx_dat < ary_dat_value.length; idx_dat++) {
                m_str_hub_dsp += ary_dat_value[idx_dat] + ",";
            }
            m_str_hub_dsp = m_str_hub_dsp.slice(0,-1);
        }
        if (
            obj_hub_msg.ary_child_pin[0].ary_st_ctl
        ) {
            var ary_ctl_value = obj_hub_msg.ary_child_pin[0].ary_st_ctl;

            m_str_hub_sel = "";

            for (var idx_ctl = 0; idx_ctl < ary_ctl_value.length; idx_ctl++) {
                m_str_hub_sel += ary_ctl_value[idx_ctl] + ",";
            }
            m_str_hub_sel = m_str_hub_sel.slice(0,-1);
        }

        m_obj_hub_msg = obj_hub_msg;
        return true;
    }
    /********** EXPORT API *********************************************************************************/
    /**
     * @returns {promises<String>} 控制芯片名称
     **/
    this.mc_util_recvcard_get_ctrlchip_name = function () {
        return get_ctrl_chip();
    };
    /**
     * @param {promises<String>} ac_name 控制芯片名称
     * @returns {promises<boolean>} 操作结果, true, false
     **/
    this.mc_util_recvcard_set_ctrlchip_name = function (ac_name) {
        return set_ctrl_chip(ac_name);
    };
    /**
     * @returns {promises<String>} HUB ID
     **/
    this.mc_util_recvcard_get_hub_name = function () {
        return get_hub_id();
    };
    /**
     * @param {promises<String>} ac_name HUB ID
     * @returns {promises<boolean>} 操作结果, true, false
     **/
    this.mc_util_recvcard_set_hub_name = function (ac_name) {
        return set_hub_id(ac_name);
    };
    /**
     * @returns {promises<String>} HUB DSP标签数据
     **/
    this.mc_util_recvcard_get_hub_dsp = function () {
        return get_hub_dsp();
    };
    /**
     * @param {promises<String>} ac_exp HUB DSP标签数据
     * @returns {promises<boolean>} 操作结果, true, false
     **/
    this.mc_util_recvcard_set_hub_dsp = function (ac_exp) {
        return set_hub_dsp(ac_exp);
    };
    /**
     * @returns {promises<String>} HUB SEL标签数据
     **/
    this.mc_util_recvcard_get_hub_sel = function () {
        return get_hub_sel();
    };
    /**
     * @param {promises<String>} ac_exp HUB DSP标签数据
     * @returns {promises<boolean>} 操作结果, true, false
     **/
    this.mc_util_recvcard_set_hub_sel = function (ac_exp) {
        return set_hub_sel(ac_exp);
    };
    /**
     * @returns {promises<String>} 行扫顺序
     **/
    this.mc_util_recvcard_get_scan_order = function () {
        return get_scan_order();
    };
    /**
     * @param {promises<String>} ac_exp 行扫顺序
     * @returns {promises<boolean>} 操作结果, true, false
     **/
    this.mc_util_recvcard_set_scan_order = function (ac_exp) {
        return set_scan_order(ac_exp);
    };
    /**
     * 图像旋转设置
     * @param {promises<Number[]>} adf_base_pnt 基准点，x, y 长度2数组
     * @param {promises<Number[]>} adf_vector 长度2数组
     * @param {promises<Float>} df_angle 角度
     * @returns {promises<boolean>} 操作结果, true, false
     **/
    this.mc_util_recvcard_set_img_rotation = function (adf_base_pnt, adf_vector, df_angle) {
        return set_rotation(adf_base_pnt, adf_vector, df_angle);
    };
    /**
     * @returns {promises<{adf_base_pnt: Array, adf_vector: Array, df_angle: Number} >} 旋转数据
     **/
    this.mc_util_recvcard_get_img_rotation = function () {
        return get_rotation();
    };
    /**
     * 图像缩放
     * @param {promises<Number[]>} adf_base_pnt 基准点，x, y 长度2数组
     * @param {promises<Number[]>} adf_scale 缩放比例 x,y比例 长度2数组
     * @returns {promises<boolean>} 操作结果, true, false
     **/
    this.mc_util_recvcard_set_img_scale = function (adf_base_pnt, adf_scale) {
        return set_scale(adf_base_pnt, adf_scale);
    };
    /**
     * @returns {promises<{adf_base_pnt: Number[], adf_vector: Number[]} >} 缩放数据
     **/
    this.mc_util_recvcard_get_img_scale = function () {
        return get_scale();
    };
    /**
     * 图像偏移
     * @param {promises<Number[]>} adf_offset 图像偏移 x, y 长度2数组
     * @returns {promises<boolean>} 操作结果, true, false
     **/
    this.mc_util_recvcard_set_img_offset = function (adf_offset) {
        return set_offset(adf_offset);
    };
    /**
     * @returns {promises<Number[]>} 缩放数据, x,y 长度2数组
     **/
    this.mc_util_recvcard_get_img_offset = function () {
        return get_offset();
    };
    /**
     * 图像变换
     * @param {promises<Number[]>} adf_rotation_base_pnt 基准点，x, y 长度2数组
     * @param {promises<Number[]>} adf_rotation_vector 长度2数组
     * @param {promises<Float>} df_rotation_angle 角度
     * @param {promises<Number[]>} adf_scale_base_pnt 基准点，x, y 长度2数组
     * @param {promises<Number[]>} adf_scale_vector 缩放比例 x,y比例 长度2数组
     * @param {promises<Number[]>} adf_offset 图像偏移 x, y 长度2数组
     * @param {promises<Number[]>} adf_matrix [4][4]
     * @returns {promises<boolean>} 操作结果, true, false
     **/
    this.mc_util_recvcard_get_img_translation_matrix = function (
        adf_rotation_base_pnt, adf_rotation_vector, df_rotation_angle,
        adf_scale_base_pnt, adf_scale_vector, adf_offset,
        adf_matrix) {
        if (!adf_matrix) {
            return false;
        }

        function mc_matrix_mutl(adf_src_matrix, adf_mult_matrix) {
            var df_dst_matrix = [
                [],
                [],
                [],
                []
            ];
            var idx_row = 0;
            var idx_col = 0;

            for (idx_col = 0; 4 > idx_col; idx_col++) {
                for (idx_row = 0; 4 > idx_row; idx_row++) {
                    df_dst_matrix[idx_row][idx_col] = 0.0;
                    for (var idx_cal = 0; 4 > idx_cal; idx_cal++) {
                        df_dst_matrix[idx_row][idx_col] += adf_src_matrix[idx_row][idx_cal] * adf_mult_matrix[idx_cal][idx_col];
                    }
                }
            }
            for (idx_col = 0; 4 > idx_col; idx_col++) {
                for (idx_row = 0; 4 > idx_row; idx_row++) {
                    adf_src_matrix[idx_row][idx_col] = df_dst_matrix[idx_row][idx_col];
                }
            }
        }

        // calculate used first rotation, then scale, the last offset, so :
        // src as : Moffset x (Mscale x (Mrotation x Pxyz))
        // used (Moffset x Mscale x Mrotation) x Pxyz

        // init return matrix
        for (var i = 0; 4 > i; i++) {
            for (var j = 0; 4 > j; j++) {
                adf_matrix[i][j] = 0;
            }
        }
        adf_matrix[0][0] = 1.0;
        adf_matrix[1][1] = 1.0;
        adf_matrix[2][2] = 1.0;
        adf_matrix[3][3] = 1.0;

        // calculate offset
        if (adf_offset && (Math.abs(adf_offset[0]) > MC_ZERO_EPSILON || Math.abs(adf_offset[1]) > MC_ZERO_EPSILON)) {
            var df_offset_matrix = [
                [1.0, 0.0, 0.0, 0.0],
                [0.0, 1.0, 0.0, 0.0],
                [0.0, 0.0, 1.0, 0.0],
                [0.0, 0.0, 0.0, 1.0]
            ];

            df_offset_matrix[0][3] = adf_offset[0];
            df_offset_matrix[1][3] = adf_offset[1];
            mc_matrix_mutl(adf_matrix, df_offset_matrix);
        }

        // calculate scale
        if (adf_scale_vector && (Math.abs(adf_scale_vector[0]) > MC_ZERO_EPSILON || Math.abs(adf_scale_vector[1]) > MC_ZERO_EPSILON)) {
            var df_scale_matrix = [
                [1.0, 0.0, 0.0, 0.0],
                [0.0, 1.0, 0.0, 0.0],
                [0.0, 0.0, 1.0, 0.0],
                [0.0, 0.0, 0.0, 1.0]
            ];

            df_scale_matrix[0][0] = adf_scale_vector[0];
            df_scale_matrix[1][1] = adf_scale_vector[1];

            if (adf_scale_base_pnt) {
                df_scale_matrix[0][3] = (1 - adf_scale_vector[0]) * adf_scale_base_pnt[0];
                df_scale_matrix[1][3] = (1 - adf_scale_vector[1]) * adf_scale_base_pnt[1];
            }

            mc_matrix_mutl(adf_matrix, df_scale_matrix);
        }

        // calculate rotation
        df_rotation_angle = -df_rotation_angle;
        df_rotation_angle -= parseInt(df_rotation_angle / 360.0, 10) * 360.0;
        if (Math.abs(df_rotation_angle) > MC_ZERO_EPSILON) {
            var df_rotation_pnt = [0.0, 0.0, 0.0];
            var df_rotation_vec = [0.0, 0.0, 0.0];

            if (adf_rotation_base_pnt) {
                df_rotation_pnt[0] = adf_rotation_base_pnt[0];
                df_rotation_pnt[1] = adf_rotation_base_pnt[1];
            }
            if (adf_rotation_vector &&
                adf_rotation_vector[0] * adf_rotation_vector[0] + adf_rotation_vector[1] * adf_rotation_vector[1] > MC_ZERO_EPSILON) {
                var df_mod_vec = Math.sqrt(adf_rotation_vector[0] * adf_rotation_vector[0] + adf_rotation_vector[1] * adf_rotation_vector[1]);

                df_rotation_vec[0] = adf_rotation_vector[0] / df_mod_vec;
                df_rotation_vec[1] = adf_rotation_vector[1] / df_mod_vec;
            } else {
                df_rotation_vec[2] = 1.0;
            }

            var u = df_rotation_vec[0];
            var v = df_rotation_vec[1];
            var w = df_rotation_vec[2];
            var uu = u * u;
            var uv = u * v;
            var uw = u * w;
            var vv = v * v;
            var vw = v * w;
            var ww = w * w;
            var au = df_rotation_pnt[0] * u;
            var av = df_rotation_pnt[0] * v;
            var aw = df_rotation_pnt[0] * w;
            var bu = df_rotation_pnt[1] * u;
            var bv = df_rotation_pnt[1] * v;
            var bw = df_rotation_pnt[1] * w;
            var cu = df_rotation_pnt[2] * u;
            var cv = df_rotation_pnt[2] * v;
            var cw = df_rotation_pnt[2] * w;

            var df_radian = df_rotation_angle / 360.0 * 2 * PI;
            var costheta = Math.cos(df_radian);
            var sintheta = Math.sin(df_radian);

            var df_rotation_matrix = [
                [1.0, 0.0, 0.0, 0.0],
                [0.0, 1.0, 0.0, 0.0],
                [0.0, 0.0, 1.0, 0.0],
                [0.0, 0.0, 0.0, 1.0]
            ];

            df_rotation_matrix[0][0] = uu + (vv + ww) * costheta;
            df_rotation_matrix[0][1] = uv * (1 - costheta) - w * sintheta;
            df_rotation_matrix[0][2] = uw * (1 - costheta) + v * sintheta;
            df_rotation_matrix[0][3] = (df_rotation_pnt[0] * (vv + ww) - u * (bv + cw)) * (1 - costheta) + (bw - cv) * sintheta;

            df_rotation_matrix[1][0] = uv * (1 - costheta) + w * sintheta;
            df_rotation_matrix[1][1] = vv + (uu + ww) * costheta;
            df_rotation_matrix[1][2] = vw * (1 - costheta) - u * sintheta;
            df_rotation_matrix[1][3] = (df_rotation_pnt[1] * (uu + ww) - v * (au + cw)) * (1 - costheta) + (cu - aw) * sintheta;

            df_rotation_matrix[2][0] = uw * (1 - costheta) - v * sintheta;
            df_rotation_matrix[2][1] = vw * (1 - costheta) + u * sintheta;
            df_rotation_matrix[2][2] = ww + (uu + vv) * costheta;
            df_rotation_matrix[2][3] = (df_rotation_pnt[2] * (uu + vv) - w * (au + bv)) * (1 - costheta) + (av - bu) * sintheta;

            df_rotation_matrix[3][0] = 0;
            df_rotation_matrix[3][1] = 0;
            df_rotation_matrix[3][2] = 0;
            df_rotation_matrix[3][3] = 1;

            mc_matrix_mutl(adf_matrix, df_rotation_matrix);
        }
        return true;
    };
    /**
     * @param {promises<Number[]>} adf_src_img_coord 基准点，x, y 长度2数组
     * @param {promises<Number[]>} adf_matrix
     * @param {promises<Float>} adf_dst_img_coord 角度
     * @returns {promises<boolean>} 操作结果, true, false
     **/
    this.mc_util_recvcard_translation_img_coordinate = function (adf_src_img_coord, adf_matrix, adf_dst_img_coord) {
        if (!adf_src_img_coord || !adf_dst_img_coord) {
            return false;
        }

        // protect memory for adf_dst_img_coord address same as adf_src_img_coord
        var df_dst_coord = [0.0, 0.0];

        if (!adf_matrix) {
            df_dst_coord[0] = adf_src_img_coord[0];
            df_dst_coord[1] = adf_src_img_coord[1];
        } else {
            df_dst_coord[0] = adf_matrix[0][0] * adf_src_img_coord[0] + adf_matrix[0][1] * adf_src_img_coord[1] + adf_matrix[0][2] * 0.0 + adf_matrix[0][3] * 1;
            df_dst_coord[1] = adf_matrix[1][0] * adf_src_img_coord[0] + adf_matrix[1][1] * adf_src_img_coord[1] + adf_matrix[1][2] * 0.0 + adf_matrix[1][3] * 1;
        }

        adf_dst_img_coord[0] = df_dst_coord[0];
        adf_dst_img_coord[1] = df_dst_coord[1];

        return true;
    };
    /**
     * @returns {promises<Number>} MODLIST个数
     **/
    this.mc_util_recvcard_get_modlist_cnt = function () {
        return get_modlist_cnt();
    };
    /**
     * @param {promises<Uint>} ui_modlist_idx MODLIST下标索引
     * @returns {promises<Number>} LEDMOD个数
     **/
    this.mc_util_recvcard_get_modlist_mod_cnt = function (ui_modlist_idx) {
        return get_mod_cnt(ui_modlist_idx);
    };
    /**
     * @param {promises<Uint>} ui_modlist_idx MODLIST下标索引
     * @param {promises<Uint>} ui_mod_idx MODLIST下标索引
     * @returns {promises<String>} MODULE_ID属性
     **/
    this.mc_util_recvcard_get_modlist_mod_name = function (ui_modlist_idx, ui_mod_idx) {
        return get_mod_id(ui_modlist_idx, ui_mod_idx);
    };
    /**
     * @param {promises<Uint>} ui_modlist_idx MODLIST下标索引
     * @returns {promises<String>} LEDMOD 文本节点值
     **/
    this.mc_util_recvcard_get_modlist_pin_pair_exp = function (ui_modlist_idx) {
        return get_modlist_pin_pair_exp(ui_modlist_idx);
    };
    /**
     * 通过id查找PIN
     * @param {promises<Uint>} ui_modlist_idx MODLIST下标索引
     * @param {promises<Uint>} ui_dsp_idx DSP id, 例如(DSP0:R1), id=1; (DSP1:G1) id=1
     * @returns {promises<String>} PIN 例如R1,G1,B1
     **/
    this.mc_util_recvcard_get_modlist_dsp_pin = function (ui_modlist_idx, ui_dsp_idx) {
        return get_modlist_dsp_pin(ui_modlist_idx, ui_dsp_idx);
    };
    /**
     * 通过PIN查找id
     * @param {promises<Uint>} ui_modlist_idx MODLIST下标索引
     * @param {promises<Uint>} ac_mod_pin_name PIN id
     * @returns {promises<String>} 返回DSP
     **/
    this.mc_util_recvcard_get_modlist_pin_dsp = function (ui_modlist_idx, ac_mod_pin_name) {
        return get_modlist_pin_dsp(ui_modlist_idx, ac_mod_pin_name);
    };
    /**
     * 删除指定pin
     * @param {promises<Uint>} ui_modlist_idx MODLIST下标索引
     * @param {promises<Uint>} ac_mod_pin_name PIN名称
     * @returns {promises<boolean>} 操作结果, true, false
     **/
    this.mc_util_recvcard_del_pinpair_by_pin = function (ui_modlist_idx, ac_mod_pin_name) {
        return delete_modlist_pin_pair_by_pin(ui_modlist_idx, ac_mod_pin_name);
    };
    /**
     * 删除指定DSP
     * @param {promises<Uint>} ui_modlist_idx MODLIST下标索引
     * @param {promises<Uint>} ui_dsp_idx DSP名称
     * @returns {promises<boolean>} 操作结果, true, false
     **/
    this.mc_util_recvcard_del_pinpair_by_dsp = function (ui_modlist_idx, ui_dsp_idx) {
        return delete_modlist_pin_pair_by_dsp(ui_modlist_idx, ui_dsp_idx);
    };
    /**
     * @param {promises<Uint>} ui_modlist_idx MODLIST下标索引
     * @param {promises<Uint>} ui_mod_idx LEDMOD下标索引
     * @returns {promises<{ui_offset_x: Number, ui_offset_y: Number,str_mirror: String,str_rotation: String,str_scale: String}>} 偏移
     **/
    this.mc_util_recvcard_get_modlist_mod_offset = function (ui_modlist_idx, ui_mod_idx) {
        var obj_offset = {};

        obj_offset.ui_offset_x = get_mod_x_offset(ui_modlist_idx, ui_mod_idx);
        obj_offset.ui_offset_y = get_mod_y_offset(ui_modlist_idx, ui_mod_idx);
        obj_offset.str_mirror = get_mod_mirror(ui_modlist_idx, ui_mod_idx);
        obj_offset.str_rotation = get_mod_rotation(ui_modlist_idx, ui_mod_idx);
        obj_offset.str_scale = get_mod_scale(ui_modlist_idx, ui_mod_idx);
        return obj_offset;
    };
    /**
     * 删除指定MODLIST下LEDMOD
     * @param {promises<Uint>} ui_modlist_idx MODLIST下标索引
     * @returns {promises<boolean>} 操作结果, true, false
     **/
    this.mc_util_recvcard_clear_modlist_mods = function (ui_modlist_idx) {
        return clear_modlist_mods(ui_modlist_idx);
    };
    /**
     * 删除指定MODLIST
     * @returns {promises<boolean>} 操作结果, true, false
     **/
    this.mc_util_recvcard_clear_modlist = function () {
        return clear_modlist();
    };
    /**
     * 设置指定MODLIST下pin_pair数据
     * @param {promises<Uint>} ui_modlist_idx MODLIST下标索引
     * @param {promises<Uint>} ac_pin_pair pin_pair数据
     * @returns {promises<boolean>} 操作结果, true, false
     **/
    this.mc_util_recvcard_set_modlist_pin_pair_exp = function (ui_modlist_idx, ac_pin_pair) {
        return set_modlist_pin_pair_exp(ui_modlist_idx, ac_pin_pair);
    };
    /**
     * @param {promises<Uint>} ui_modlist_idx MODLIST下标索引
     * @param {promises<Uint>} ui_mod_idx LEDMOD下标索引
     * @param {promises<String>} ac_mod_id 设置的MODULE_ID属性
     * @param {promises<Uint>} ui_offset_x 设置的OFFSET_X属性
     * @param {promises<Uint>} ui_offset_y 设置的OFFSET_Y属性
     * @param {promises<Uint>} str_mirror 设置的镜像模式
     * @param {promises<Uint>} str_rotation 设置的旋转表达式
     * @param {promises<Uint>} str_scale 设置的缩放表达式
     * @param {promises<String>} str_cut 裁剪表达式
     * @returns {promises<boolean>} 操作结果, true, false
     **/
    this.mc_util_recvcard_set_modlist_mod_info = function (ui_modlist_idx, ui_mod_idx, ac_mod_id, ui_offset_x, ui_offset_y,str_mirror,str_rotation,str_scale,str_cut) {
        return set_mod_info(ui_modlist_idx, ui_mod_idx, ac_mod_id, ui_offset_x, ui_offset_y,str_mirror,str_rotation,str_scale,str_cut);
    };
    /**
     * 反序MODLIST下的LEDMOD
     * @param {promises<Uint>} ui_modlist_idx MODLIST下标索引
     * @returns {promises<boolean>} 操作结果, true, false
     **/
    this.mc_util_recvcard_set_modlist_reverse_mod_order = function (ui_modlist_idx) {
        return reverse_modlist_mod_order(ui_modlist_idx);
    };
    /**
     * 获取xml数据
     * @returns {promises<boolean>} xml数据
     **/
    this.mc_util_recvcard_get_xml = function () {
        return get_xml_data();
    };
    /**
     * 解析xml数据
     * @param {promises<Uint>} ac_xml_buff xml字符串
     * @returns {promises<boolean>} 操作结果, true, false
     **/
    this.mc_util_recvcard_set_xml = function (ac_xml_buff) {
        return set_xml_data(ac_xml_buff);
    };
    /**
     * 清空所有数据
     * @returns {promises<boolean>} 操作结果, true, false
     **/
    this.mc_util_recvcard_reset = function () {
        return reset();
    };

    /* **************************** Xsc **************************** */
    /**
     * 获取箱体下第一个模组名称
     * @returns {Promises<String>} 箱体内第一个模组名称
     **/
    this.mc_util_recvcard_get_fisrt_mod_name = function () {
        return get_first_mod_name();
    };
    /**
     * 存入箱体尺寸
     * @param {Promises<Number>} ui_recvcard_width
     * @param {Promises<Number>} ui_recvcard_height
     * @returns {Promise<Boolean>} 存入结果
     */
    this.mc_util_recvcard_set_size = function (ui_recvcard_width,ui_recvcard_height) {
        if (
            "number" !== typeof ui_recvcard_width || isNaN(ui_recvcard_width) ||
            "number" !== typeof ui_recvcard_height || isNaN(ui_recvcard_height)
        ) {
            return false;
        }
        m_obj_revcard_msg.ui_img_w = ui_recvcard_width;
        m_obj_revcard_msg.ui_img_h = ui_recvcard_height;
        return true;
    };
    /**
     * 获取存入尺寸
     * @returns {Promise<Object>} {ui_box_w:Number,ui_box_h:Number} 宽度,高度
     */
    this.mc_util_recvcard_get_size = function () {
        return {
            ui_box_w: m_obj_revcard_msg.ui_img_w,
            ui_box_h: m_obj_revcard_msg.ui_img_h
        };
    };

    /**
     * 存入hub描述对象
     * @param {Promise<Object>} obj_hub_msg hub描述对象
     * @returns {Promise<Boolean>} 储存结果
     */
    this.mc_util_recvcard_set_hub_msg = function (obj_hub_msg) {
        return set_hub_msg(obj_hub_msg);
    };
    /**
     * 获取hub描述对象
     * @returns {Promise<Object>} hub描述对象
     */
    this.mc_util_recvcard_get_hub_msg = function () {
        return m_obj_hub_msg;
    };
}
